package com.ajmd.onlineexam.scheduledTask;

import com.ajmd.onlineexam.entity.ExamPO;
import com.ajmd.onlineexam.entity.PersonExamPO;
import com.ajmd.onlineexam.enumeration.StaticFinalValue;
import com.ajmd.onlineexam.mapper.ExamMapper;
import com.ajmd.onlineexam.mapper.PersonExamMapper;
import com.ajmd.onlineexam.mapper.StudentMapper;
import com.ajmd.onlineexam.service.ExamService;
import com.ajmd.onlineexam.service.MessageService;
import com.ajmd.onlineexam.service.PersonExamService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.sql.Timestamp;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author ajmd
 * @since 2023/5/3 22:51
 *
 *考试定时任务
 */
@Component
public class ExamScheduled {
    @Resource
    private ExamMapper examMapper;
    @Resource
    private StudentMapper studentMapper;
    @Resource
    private PersonExamMapper personExamMapper;
    @Resource
    private MessageService messageService;

    /**
     * 考前消息通知提醒
     */
//    @Scheduled(cron = "0/10 * * * * ?")//每10秒执行一次
    public void preExamReminder(){
        //查询需要提醒的考试表
        LambdaQueryWrapper<ExamPO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        //当前时间-10秒 < 开始时间 - 提前通知时间 <= 当前时间，即应该提醒了
        lambdaQueryWrapper.apply(" TIMESTAMPDIFF(second, current_timestamp(), "+
                " start_time) > (pre_exam_reminder*60 - 10) "+
                " and TIMESTAMPDIFF(second, current_timestamp(), start_time) <= pre_exam_reminder*60 ");
        List<ExamPO> examPOS = examMapper.selectList(lambdaQueryWrapper);
        if(ObjectUtils.isEmpty(examPOS)){
            return;
        }
        //取得考试ids
        List<String> examIds = examPOS.stream().map(ExamPO::getId).collect(Collectors.toList());
        LambdaQueryWrapper<PersonExamPO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(PersonExamPO::getExamId,examIds);
        //查询出相关考生考试记录
        List<PersonExamPO> personExamPOList = personExamMapper.selectList(queryWrapper);
        //按照examId分组，每组是studentId的Set集合
        Map<String, Set<String>> collect = personExamPOList.stream().collect(Collectors.groupingBy(
                PersonExamPO::getExamId, Collectors.mapping(PersonExamPO::getStudentId, Collectors.toSet())
        ));
        //封装参数
        Map<String, Map<String, Object>> stringMapMap = new HashMap<>();
        for(ExamPO examPO:examPOS){
            Map<String, Object> value = new HashMap<>();
            String msg = "考试题型！您的考试《"+examPO.getExamName()+"》"+examPO.getPreExamReminder()+"分钟后即将开始，请注意时间！";
            value.put("msg",msg);
            value.put("sendAccount",examPO.getCreatePerson());
            value.put("studentIds",collect.get(examPO.getId()));
            value.put("sendType",examPO.getCreatorType());
            stringMapMap.put(examPO.getId(),value);
        }
        //为需要提醒的考试的所有学生增加一条消息记录
        messageService.batchInsert(stringMapMap);

        //todo 往邮箱发信息
    }


    /**
     * 考试状态更改
     */
//    @Scheduled(cron = "0/10 * * * * ?")//每10秒执行一次
    public void updateStatus(){
        //考试开始时间早于等于当前时间，改为进行中
        LambdaUpdateWrapper<ExamPO> updateStartWrapper = new LambdaUpdateWrapper<>();
        updateStartWrapper.set(ExamPO::getStatus, StaticFinalValue.IN_PROGRESS)
                .eq(ExamPO::getStatus, StaticFinalValue.NOT_STARTED)
                .le(ExamPO::getStartTime,new Timestamp(System.currentTimeMillis()));
        examMapper.update(null,updateStartWrapper);

        //考试结束时间早于等于当前时间，改为已结束
        LambdaUpdateWrapper<ExamPO> updateEndWrapper = new LambdaUpdateWrapper<>();
        updateEndWrapper.set(ExamPO::getStatus, StaticFinalValue.ENDED)
                .eq(ExamPO::getStatus, StaticFinalValue.IN_PROGRESS)
                .le(ExamPO::getEndTime,new Timestamp(System.currentTimeMillis()))
                .isNotNull(ExamPO::getEndTime);
        examMapper.update(null,updateEndWrapper);
    }
}
